#include "memberschedule.h"

#include <QDir>
#include <QFile>
#include <QLabel>
#include <QJsonObject>
#include <QHeaderView>
#include <QJsonDocument>
#include <QTableWidgetItem>
#include <QPushButton>
#include <QMessageBox>
#include <QModelIndex>
#include <QLineEdit>
#include <QListWidget>
#include <QApplication>

#define NONE_EXIST      (0)
#define ALL_EXIST          (1)

QList<QString> memberAbilityLevelList = {"培训期", "非培训期"};
QList<QString> memberRequirementList = {"无", "不上节假日"};
QString jsonDirPath ;
QString jsonFilePath;

bool compareMemberClassName(const MemberClass* p1, const MemberClass* p2);
bool compareStringName(QString name1,  QString name2);
MemberClass* findMemberClassFromName( QList<MemberClass *> memberList, QString name);

bool compareMemberClassName(const MemberClass* p1, const MemberClass* p2)
{
        return (p1->getMemberName().localeAwareCompare(p2->getMemberName()) < 0);
}

bool compareStringName(QString name1,  QString name2)
{
        return (name1.localeAwareCompare(name2) < 0);
}

MemberClass* findMemberClassFromName( QList<MemberClass *> memberList, QString name)
{
    MemberClass* pTmp = NULL;
    for(int i = 0; i < memberList.count(); i++){
        pTmp = memberList.at(i);
        if(NULL == pTmp)    continue;
        if(name == pTmp->getMemberName())    break;
    }

    return pTmp;
}

MemberSchedule::MemberSchedule(QWidget *parent)
    : QWidget{parent}
{
}

MemberSchedule::MemberSchedule(QWidget *parent, QStackedWidget * pStackWidget)
{
    setParent(parent);
    this->myParent = parent;
    this->pStackWidget = pStackWidget;

    pSelectTeacherDialog = NULL;
    pSelectTeacherComBox = NULL;
    pSelectTeacherLabel = NULL;
    tableLayout = NULL;
    btnLayout = NULL;
    widgetLayout = NULL;
    jsonFile = NULL;

    initJsonFile();

    // 初始化tabelWidget控件
    initTabelWidget();

     // 加载tabelWidget中的数据
     dataLoad();

     // 为MemberSchedule界面添加按钮并初始化
     initMemberSchedulePushButton();
}

MemberSchedule::~MemberSchedule(void)
{
    closeJsonFile();
    delete jsonFile;
    jsonFile = NULL;
}

void MemberSchedule::initTabelWidget(void)
{
    pTable = new MyMemberTable(myParent);

    // 创建列表头，确定列数，最后一个空值是用来存放 删除 按钮的
#ifdef REQUIREMENT_ENABLE
    QStringList colLabels = {"姓名" , "是否为培训期" , "特殊要求" , "带教人员" , " ", " "};
#else
    QStringList colLabels = {"姓名" , "是否为培训期" , "带教人员" , " ", " "};
#endif  // REQUIREMENT_ENABLE

    pTable->createHorizontalHeader(colLabels);

    // 设置表头样式
    pTable->setMemberHorizontalHeaderStyle(QFont("song", 15), TABLEWIDGET_HORIZONTALHEADER_STYLE, false);

    // 设置布局
    if(NULL != tableLayout){
        deleteBoxLayout(tableLayout);
        delete tableLayout;
    }
    tableLayout = new QHBoxLayout;
    tableLayout->addWidget(pTable);

    // 设置监听cellChanged信号，当单元格的数据发生变换时，设置当前单元格的样式
    connect(pTable, &MyMemberTable::cellChanged, this, &MemberSchedule::slot_tableWidget_cellChanged);

    return;
}

template<class Type>
void MemberSchedule::deleteBoxLayout(Type *t)
{
    if(NULL == t)
        return;

    QLayoutItem* child;
    while((child = t->takeAt(0)) != 0){
        if(NULL == child->widget())
            continue;
        //必须将parent置为nullpptr，否则不消失
        t->removeWidget(child->widget());
        child->widget()->setParent(NULL);
        delete child;
    }

    return;
}

void MemberSchedule::dataLoad(void)
{
    QString name, teacherName;
    int iLevel = 0, iRequirement = 0;
    QJsonObject obj;
    QList<MemberClass*> memberList;
    readJsonData(obj);

    transferJsonObjectToMemberClass(&obj, &memberList);
    pTable->setRowCount(memberList.size());

    for (int i = 0; i < memberList.size(); i++){
        name = memberList.at(i)->getMemberName();
        iLevel = memberList.at(i)->getMemberAbilityLevelIndex();
        iRequirement = memberList.at(i)->getMemberRequirementIndex();
        teacherName = memberList.at(i)->getTeacherName();

        if(iLevel < MEMBER_ABILITY_LEVEL_1 || iLevel > MEMBER_ABILITY_LEVEL_4)
            iLevel = MEMBER_ABILITY_LEVEL_1;

        // 姓名单元格
        pTable->createItem(name, i, COLUMN_NAME);

        // 能力等级单元格，创建combobox控件
        initLevelComboBox(pTable, iLevel, i);

#ifdef REQUIREMENT_ENABLE
        // 特殊要求单元格，创建combobox控件
        initRequireComboBox(pTable, iRequirement, i);
#endif  // REQUIREMENT_ENABLE

        // 带教人员单元格
        pTable->createItem(teacherName, i, COLUMN_TEACHER);

        // 删除人员按钮
        setPushButtonDelete(i, COLUMN_PUSHBUTTON_DELETE);

        // 删除带教人员按钮
        setPushButtonTeacherDelete(i, COLUMN_PUSHBUTTON_TEACHER_DELETE);
    }

    // 按姓名列升序显示
    pTable->sortItems(COLUMN_NAME, Qt::AscendingOrder);
    qSort(memberList.begin(), memberList.end(), compareMemberClassName);
    updateMemberList(memberList, MEMBERLIST);
    return;
}

void MemberSchedule::transferJsonObjectToMemberClass(QJsonObject *pObj, QList<MemberClass*> *plist)
{
    if(NULL == pObj || NULL == plist){
        QLOG_WARN() << "NULL == pObj || NULL == plist";
        return;
    }

    MemberClass *pMember = NULL;

    QStringList keys = pObj->keys();
    for(int i=0; i<keys.size(); ++i) {
        QString key = keys.at(i);
        QJsonValue value = pObj->value(key);
        if(false == value.isObject())
            continue;

        QJsonObject subObj = value.toObject();
        QStringList ls = subObj.keys();
        for(int i = 0; i < ls.size(); i++) {
            QJsonValue subVal = subObj.value(ls.at(i));
            if(false == subVal.isString() && false == subVal.isDouble())
                continue;

            // 当有数据时才申请内存
            if (0 == i)                               pMember = new MemberClass;
            if (NULL == pMember)        break;

            if ("姓名" == ls.at(i)){
                pMember->setMemberName(subVal.toString());
            }
            else if ("能力等级" == ls.at(i)){
                pMember->setMemberAbilityLevelIndex(subVal.toInt());
            }
            else if ("特殊选项" == ls.at(i)){
#ifdef REQUIREMENT_ENABLE
                pMember->setMemberRequirementIndex(subVal.toInt());
#endif  // REQUIREMENT_ENABLE
            }

            else if ("带教人员" == ls.at(i)){
                pMember->setTeacherName(subVal.toString());
            }
            else
                QLOG_DEBUG() <<  ls.at(i) <<"is invalid";

            // 将新创建的MemberClass追加到QList<MemberClass*> 结尾，注意释放
            if(ls.size() - 1 == i)
                plist->append(pMember);
        }
    }

    return;
}

void MemberSchedule::appendMemberList(QList<MemberClass *> & memberList, QJsonObject Obj)
{
    MemberClass* pMember = new MemberClass;
    if(NULL == pMember){
        QLOG_WARN() << "NULL == pMember";
        return;
    }

    pMember->setMemberName(Obj.take("姓名").toString());
    pMember->setMemberAbilityLevelIndex(Obj.take("能力等级").toInt());
    pMember->setMemberRequirementIndex(Obj.take("特殊选项").toInt());
    pMember->setTeacherName(Obj.take("带教人员").toString());

    memberList.append(pMember);

    return;
}

void MemberSchedule::updateMemberList(QList<MemberClass *> srcList, QList<MemberClass *> & dstList)
{
    for(int i = 0; i< dstList.count(); i++){
        MemberClass * pTmp = dstList.at(i);
        if(NULL != pTmp){
            delete pTmp;
            pTmp = NULL;
        }
    }

    dstList.clear();
    qSort(srcList.begin(), srcList.end(), compareMemberClassName);
    dstList = srcList;

    return;
}

int MemberSchedule::teacherForRookie(QList<MemberClass*> & memberList)
{
    int ret = -1, res = -1;
    int iRowCount = pTable->rowCount();
    QTableWidgetItem * pItemTeacher = NULL;
    QTableWidgetItem * pItemName = NULL;
    MyCombobox * qCombo = NULL;

    for(int i = 0; i < iRowCount; i++){
        qCombo = (MyCombobox *)pTable->cellWidget(i, COLUMN_ABILITY_LEVEL);
        if(NULL == qCombo)   continue;

        if(MEMBER_ABILITY_LEVEL_1 != qCombo->currentIndex())    continue;

        pItemTeacher = pTable->item(i, COLUMN_TEACHER);
        pItemName = pTable->item(i, COLUMN_NAME);
        if(NULL == pItemTeacher || NULL == pItemName)   continue;

        // 新人，但没有指明带教
        if("" == pItemTeacher->text()){
SELETE_TEACHER:
            // 弹出对话框，选择合格带教人员
            // 0代表已更改，!0代表未更改
            res = seleteTeacher(pItemName->text(), memberList);

            // 将选择的带教人员名称写入单元格
            MemberClass* pTmp = findMemberClassFromName(memberList, pItemName->text());
            if(NULL == pTmp){
                QLOG_DEBUG() << "NULL == pTmp";
                continue;
            }
            pItemTeacher->setText(pTmp->getTeacherName());
            if(0 == res)    ret = 0;
        }
        // 新人，已指明带教，需检验带教的合法性
        else {
            // 返回 0 代表合法，!0为非法，需要重新调整
            res = checkTeacherValid(pItemTeacher->text(), memberList);
            if(0 != res){
                // 弹出警告对话框
                QMessageBox *pWarnBox = new QMessageBox(QMessageBox::Warning, "警告", QString("%1的带教人员能力等级需为骨干").arg(pItemName->text()), QMessageBox::Ok, this, Qt::Dialog);
                pWarnBox->exec();
                goto SELETE_TEACHER;
            }
        }
    }

    return ret;
}

int MemberSchedule::seleteTeacher(QString name, QList<MemberClass *> &memberList)
{
    QStringList teacherList;

    if(NULL == pSelectTeacherDialog){
        pSelectTeacherDialog = new QDialog(myParent);
        if(NULL == pSelectTeacherDialog){
            QLOG_WARN() <<"NULL == pGetScheduleMonthDialog";
            return -1;
        }
        pSelectTeacherDialog->setFixedSize(QSize(300, 250));
        pSelectTeacherDialog->setWindowTitle("选择带教人员");
        pSelectTeacherDialog->setWindowFlags(Qt::Dialog | Qt::WindowCloseButtonHint);

        createDialogLabel(pSelectTeacherDialog, QPoint(12, 10), QSize(275, 35), "处于培训期的组员需要被指定带教人员", QFont("Microsoft YaHei", 12));
        initTeacherDialogPushbutton(pSelectTeacherDialog);
    }

    // 重新设定combobox前的文字
    if(NULL != pSelectTeacherLabel)
        delete pSelectTeacherLabel;
    pSelectTeacherLabel  = createDialogLabel(pSelectTeacherDialog, QPoint(20, 70), QSize(170, 35), QString("请为<b>%1</b>指定人员:").arg(name), QFont("Microsoft YaHei", 12));

    // 筛选合格的带教人员名单
    getTeacherName(teacherList, memberList);

    // pSelectTeacherComBox不存在就新建，存在就delete后重建，目的是确保list是最新的
    initDialogComboBox(pSelectTeacherDialog, pSelectTeacherComBox, QPoint(180, 70), QSize(105, 35), teacherList);

    // 以模态对话框形式运行
    pSelectTeacherDialog->exec();

    return 0;
}

void MemberSchedule::getTeacherName(QStringList &teacherList, QList<MemberClass *> memberList)
{
    MemberClass *pTmp = NULL;
    for(int i = 0; i < memberList.count(); i++){
        pTmp = memberList.at(i);
        if(NULL == pTmp)    continue;

        if(pTmp->getMemberAbilityLevelIndex() >= MEMBER_ABILITY_LEVEL_4)
            teacherList.append(pTmp->getMemberName());
    }

    qSort(teacherList.begin(), teacherList.end(), compareStringName);
    return;
}

int MemberSchedule::checkTeacherValid(QString name, QList<MemberClass *> memberList)
{
    int ret = -1;

    MemberClass *pTmp = findMemberClassFromName(memberList, name);
    if(NULL == pTmp){
        QLOG_WARN() << "NULL == pTmp";
        return ret;
    }

    if(pTmp->getMemberAbilityLevelIndex() >= MEMBER_ABILITY_LEVEL_4)
        ret = 0;

    return ret;
}

void MemberSchedule::initMemberSchedulePushButton(void)
{
    QPushButton *pBtnAddMember = new QPushButton("添加人员", myParent);
    QPushButton *pBtnSave = new QPushButton("下一步", myParent);
    QPushButton *pBtnCancel = new QPushButton("返回主界面", myParent);

    pBtnAddMember->setStyleSheet(TABLEWIDGET_PUSHBUTTON_STYLE);
    pBtnSave->setStyleSheet(TABLEWIDGET_PUSHBUTTON_STYLE);
    pBtnCancel->setStyleSheet(TABLEWIDGET_PUSHBUTTON_STYLE);

    // 设置监听函数
    // pBtnAddMember点击之后会在pTableWidget行尾添加一行
    connect(pBtnAddMember, &QPushButton::clicked, this, &MemberSchedule::slot_btnAddMember_clicked);
    // pBtnSave点击之后会在pTableWidget内容保存到json文件
    connect(pBtnSave, &QPushButton::clicked, this, &MemberSchedule::slot_btnSave_clicked);
    // pBtnCancel点击之后会返回主界面
    connect(pBtnCancel, &QPushButton::clicked, this, &MemberSchedule::slot_btnCancel_clicked);

    // 设置布局
    if(NULL != btnLayout){
        deleteBoxLayout(btnLayout);
        delete btnLayout;
    }
    btnLayout = new QHBoxLayout;
    btnLayout->addStretch(1);
    btnLayout->addWidget(pBtnAddMember);
    btnLayout->addStretch(6);
    btnLayout->addWidget(pBtnSave);
    btnLayout->addStretch(1);
    btnLayout->addWidget(pBtnCancel);
    btnLayout->addStretch(1);

    //设置总体布局
    if(NULL != widgetLayout) {
        deleteBoxLayout(widgetLayout);
        delete widgetLayout;
    }
    if(NULL != tableLayout && NULL != btnLayout && NULL == widgetLayout){
        widgetLayout = new QVBoxLayout;
        widgetLayout->addLayout(tableLayout);
        widgetLayout->addLayout(btnLayout);
        myParent->setLayout(widgetLayout);
    }

    return;
}

void MemberSchedule::setPushButtonDelete(int row, int column)
{
    if(COLUMN_PUSHBUTTON_DELETE != column){
        QLOG_WARN() << "column is not COLUMN_PUSHBUTTON_DELETE";
        return;
    }

    if(NULL != pTable->cellWidget(row, column)){
        QLOG_WARN() << "cellWidget is not null";
        return;
    }

    QPushButton *pPushBtn = new QPushButton("删除", myParent);
    // 设置 pPushBtn 样式
    pPushBtn->setFont(QFont("Microsoft YaHei", 12));
    pPushBtn->setStyleSheet(TABLEWIDGET_DELETE_PUSHBUTTON_STYLE);
    pTable->setCellWidget(row, column, pPushBtn);

    // 监听 clicked 信号
    connect(pPushBtn, &QPushButton::clicked, this, &MemberSchedule::slot_pushButtonDelete_clicked);

    return;
}

void MemberSchedule::setPushButtonTeacherDelete(int row, int column)
{
    if(COLUMN_PUSHBUTTON_TEACHER_DELETE != column){
        QLOG_WARN() << "column is not COLUMN_PUSHBUTTON_TEACHER_DELETE";
        return;
    }

    if(NULL != pTable->cellWidget(row, column)){
        QLOG_WARN() << "cellWidget is not null";
        return;
    }

    QPushButton *pPushBtn = new QPushButton("删除带教人员", myParent);
    // 设置 pPushBtn 样式
    pPushBtn->setFont(QFont("Microsoft YaHei", 12));
    pPushBtn->setStyleSheet(TABLEWIDGET_DELETE_PUSHBUTTON_STYLE);
    pTable->setCellWidget(row, column, pPushBtn);

    // 监听 clicked 信号
    connect(pPushBtn, &QPushButton::clicked, this, &MemberSchedule::slot_pushButtonTeacherDelete_clicked);

    return;
}

void MemberSchedule::initLevelComboBox(MyMemberTable *pTable, int index, int row)
{
    if(NULL == pTable){
        QLOG_WARN() << "NULL == pTable";
        return ;
    }

    MyCombobox *pComBox = new MyCombobox(myParent);

    pComBox->setComboBoxStyle(pComBox, QFont("Microsoft YaHei", 12), memberAbilityLevelList, TABLEWIDGET_MEMBER_COMBOBOX_STYLE);
    pComBox->setCurrentIndex(index);
    pTable->setCellWidget(row, COLUMN_ABILITY_LEVEL, pComBox);

    // 设置tooltip
    setLevelToolTip(pComBox, index);

    // 监听pComBox的currentIndexChanged信号，当索引值改变时触发
    connect(pComBox, QOverload<int>::of(&MyCombobox::currentIndexChanged), this, &MemberSchedule::slot_LevelComboBox_currentIndexChanged);
    return;
}

#ifdef REQUIREMENT_ENABLE
void MemberSchedule::initRequireComboBox(MyMemberTable *pTable, int index, int row)
{
    if(NULL == pTable){
        QLOG_WARN() << "NULL == pTable";
        return ;
    }

    MyCombobox *pComBox = new MyCombobox(myParent);

    pComBox->setComboBoxStyle(pComBox, QFont("Microsoft YaHei", 12), memberRequirementList, TABLEWIDGET_MEMBER_COMBOBOX_STYLE);
    pComBox->setCurrentIndex(index);
    pTable->setCellWidget(row, COLUMN_REQUIREMENT, pComBox);

    return;
}
#endif  // REQUIREMENT_ENABLE

void MemberSchedule::setLevelToolTip(MyCombobox *pComBox, int level)
{
    if(NULL == pComBox){
        QLOG_WARN() << "NULL == pComBox";
        return ;
    }

    QString toolTipString;
    if(MEMBER_ABILITY_LEVEL_1 == level)
        toolTipString = "处于培训期的新人";
    else
         toolTipString = "能独立处理大多数问题，具有带新人的能力";

    pComBox->setToolTip(toolTipString);
    return;
}

void MemberSchedule::initTeacherDialogPushbutton(QDialog *pDialog)
{
    if(NULL == pDialog){
        QLOG_WARN() << "NULL == pComBox";
        return ;
    }

    QPushButton * pButtonYes = createDialogPushButton(pDialog, QPoint(165, 180), QSize(100, 35), "确定");
    if(NULL == pButtonYes){
        QLOG_WARN() << "NULL == pButtonYes";
        return;
    }

    connect(pButtonYes, &QPushButton::clicked, this, &MemberSchedule::slot_teacherDialogBtn_clicked);

    return;
}

QPushButton *MemberSchedule::createDialogPushButton(QDialog *pDialog, QPoint point, QSize size, QString text)
{
    if(NULL == pDialog){
        QLOG_WARN() << "NULL == Dialog";
        return NULL;
    }

    QPushButton * pButton = new QPushButton(text, pDialog);
    pButton->move(point);
    pButton->setFixedSize(size);
    pButton->setStyleSheet(DATESET_DIALOG_PUSHBUTTON_STYLE);

    return pButton;
}

QLabel * MemberSchedule::createDialogLabel(QDialog *pDialog, QPoint point, QSize size, QString text, QFont font)
{
    if(NULL == pDialog){
        QLOG_WARN() << "NULL == Dialog";
        return NULL;
    }

    QLabel *pLabel = new QLabel(text, pDialog);
    pLabel->move(point);
    pLabel->setFixedSize(size);
    pLabel->setFont(font);

    return pLabel;
}

void MemberSchedule::initDialogComboBox(QDialog *pDialog, MyCombobox * & pComBox, QPoint point, QSize size, QStringList strlist)
{
    if(NULL == pDialog){
        QLOG_WARN() << "NULL == Dialog";
        return;
    }

    if(NULL != pComBox)
        delete pComBox;

    pComBox = new MyCombobox(pDialog);
    pComBox->move(point);
    pComBox->setFixedSize(size);
    pComBox->setComboBoxStyle(pComBox, QFont("Microsoft YaHei", 14), strlist, TABLEWIDGET_MEMBER_TEACHER_COMBOBOX_STYLE);

    return;
}

void MemberSchedule::initJsonFile()
{
    jsonDirPath = QApplication::applicationDirPath() + "/data";
    jsonFilePath = jsonDirPath + "/member.json";
    QDir folder(jsonDirPath);
    if(false == folder.exists()){
        if(true == folder.mkpath(jsonDirPath)){
            QLOG_INFO() << jsonDirPath << "文件夹创建成功。";
        }
    }

    jsonFile = new QFile(jsonFilePath);
    return;
}

void MemberSchedule::openJsonFile(QIODevice::OpenModeFlag flag)
{

    if(false == jsonFile->exists()){
        QLOG_WARN() << jsonFilePath << "文件不存在，正在重新创建文件。";
        jsonFile->open(QIODevice::WriteOnly);
        jsonFile->close();
    }

   if(true == jsonFile->open(flag)){
       QLOG_WARN() << jsonFilePath << "文件打开成功。";
   } else{
       QLOG_WARN() << jsonFilePath << "文件打开失败。";
   }

   return ;
}

void MemberSchedule::readJsonData(QJsonObject &obj)
{
    openJsonFile(QIODevice::ReadOnly);

    // 文件所有者没有读权限
    if(NULL == jsonFile || 0 == (jsonFile->permissions() & QFileDevice::ReadOwner)){
        QLOG_WARN() << "文件所有者没有读权限，无法读取文件！！！";
        return;
    }

    QByteArray json = jsonFile->readAll();
    if(json.size() >= 0){
        QLOG_INFO() << "文件读取成功。";
        closeJsonFile();
    }

    QJsonDocument doc = QJsonDocument::fromJson(json);
    if(false == doc.isObject())     return ;
    obj = doc.object();

    return;
}

void MemberSchedule::writeJsonData(QJsonObject &obj)
{
    openJsonFile(QIODevice::WriteOnly);

    // 文件所有者没有写权限
    if(NULL == jsonFile || 0 == (jsonFile->permissions() & QFileDevice::WriteOwner)){
        QLOG_WARN() << "文件所有者没有写权限，无法写文件！！！";
        return;
    }

    // 保存至文件
    QJsonDocument doc(obj);
    QByteArray json = doc.toJson();
    if(jsonFile->write(json) > 0){
        QLOG_INFO() << "文件写入成功。";
    }
    closeJsonFile();
    return;
}

void MemberSchedule::closeJsonFile()
{
    if(NULL != jsonFile)
        jsonFile->close();

    return;
}

void MemberSchedule::slot_memberScheduleAction_clicked(void)
{
    if (STACKWIDGET_MEMBERSCHEDULE_INDEX == pStackWidget->currentIndex()){
        QLOG_WARN() << "(STACKWIDGET_MEMBERSCHEDULE_INDEX == pStackWidget->currentIndex()";
        return;
    }

    pStackWidget->setCurrentIndex(STACKWIDGET_MEMBERSCHEDULE_INDEX);

    return;
}

void MemberSchedule::slot_btnAddMember_clicked(void)
{
    // 首先断开 cellChanged 信号的监听
    disconnect(pTable, &MyMemberTable::cellChanged, this, &MemberSchedule::slot_tableWidget_cellChanged);

    int row = pTable->rowCount();

    // 插入新行
    pTable->insertRow(row);
    pTable->setCurrentCell(row, COLUMN_PUSHBUTTON_DELETE);

    // 创建姓名单元格
    pTable->createItem("", row, COLUMN_NAME);

    // 创建能力等级单元格 combobox控件
    initLevelComboBox(pTable, MEMBER_ABILITY_LEVEL_4, row);

#ifdef REQUIREMENT_ENABLE
    // 创建特殊要求单元格 combobox控件
    initRequireComboBox(pTable, MEMBER_REQUIREMENT_NONE, row);
#endif  // REQUIREMENT_ENABLE

    // 创建带教人员单元格
    pTable->createItem("", row, COLUMN_TEACHER);

    // 创建删除按钮
    setPushButtonDelete(row, COLUMN_PUSHBUTTON_DELETE);

    // 创建删除带教人员按钮
    setPushButtonTeacherDelete(row, COLUMN_PUSHBUTTON_TEACHER_DELETE);

    // 再链接上 cellChanged 信号的监听
    connect(pTable, &MyMemberTable::cellChanged, this, &MemberSchedule::slot_tableWidget_cellChanged);
    return;
}

void MemberSchedule::slot_btnSave_clicked(void)
{
    QJsonObject Obj;
    QJsonObject subObj;
    // *_EXIST，表示subObj含有的属性
    int iFlag = NONE_EXIST;
    int iRowCount = pTable->rowCount();
    int iColumnCount = pTable->columnCount();
    QList< int > iRemoveRowList;
    QTableWidgetItem * pItem = NULL;
    MyCombobox * qCombo = NULL;
    QString namestring;
    QList<MemberClass*> memberList; // 存放当前所有成员信息的链表，用于替换更新MEMBERLIST

    for (int i = 0; i < iRowCount; i++){

        // 先将残留数据清空
        subObj.remove("姓名");
        subObj.remove("能力等级");
#ifdef REQUIREMENT_ENABLE
        subObj.remove("特殊选项");
#endif  // REQUIREMENT_ENABLE
        subObj.remove("带教人员");
        iFlag = NONE_EXIST;

        for (int j = 0; j < iColumnCount; j++){
            if(COLUMN_NAME == j){
                pItem = pTable->item(i, j);
                if(NULL == pItem || "" == pItem->text())    break;

                iFlag = ALL_EXIST;
                subObj.insert("姓名", pItem->text());
                namestring = pItem->text();
            }
            else if(COLUMN_ABILITY_LEVEL == j){
                qCombo = (MyCombobox *)pTable->cellWidget(i, j);
                if(NULL == qCombo)    break;
                subObj.insert("能力等级", qCombo->currentIndex());
            }
#ifdef REQUIREMENT_ENABLE
            else if(COLUMN_REQUIREMENT == j){
                qCombo = (MyCombobox *)pTable->cellWidget(i, j);
                if(NULL == qCombo)    break;
                subObj.insert("特殊选项", qCombo->currentIndex());
            }
#endif  // REQUIREMENT_ENABLE
            else if(COLUMN_TEACHER == j){
                pItem = pTable->item(i, j);
                if(NULL == pItem)    break;
                subObj.insert("带教人员", pItem->text());
            }
            else
                break;
        }

        // 如果当前行不是所有数据都存在，就不保存，并提出告警
        if(ALL_EXIST != iFlag){
            if(NONE_EXIST == iFlag) {
               // 如果添加了空行，就把行索引值添加到list，统一删除，排除由于删除后行顺序发改变产生的干扰
                iRemoveRowList.push_front(i);
                continue;
            }

            // 高亮当前行
            pTable->highLighterRow(SELETE_ROW_HIGHLIGHT_BACKGROUND_STYLE, i);

            // 弹出警告对话框
            QMessageBox *pWarnBox = new QMessageBox(QMessageBox::Warning, "警告", "存在行数据填充不完整", QMessageBox::Ok, this, Qt::Dialog);
            pWarnBox->exec();

            pTable->CancelHighLighterRow(SELETE_ROW_DEFAULT_BACKGROUND_STYLE);
            continue;
        }

        // 将 姓名 作为存放subObj的key
        Obj.insert(namestring, subObj);
        // 追加至memberList，最后汇总
        appendMemberList(memberList, subObj);
    }

    if(0 == memberList.count()){
        QMessageBox::warning(this, "警告", "尚未添加成员，请添加后再次重试！", QMessageBox::Yes);
        return;
    }

    // 如果添加了空行，移除空行
    for(int i = 0; i < iRemoveRowList.count(); i++)
        pTable->removeRow(iRemoveRowList.at(i));

    // 汇总更新MEMBERLIST
    updateMemberList(memberList, MEMBERLIST);

    // 检索所有 处于培训期的人，
    // 如果带教人员一栏为空，则弹出对话框来选择带教人员
    // 如果带教人员一栏不为空，则检测带教人员的合法性，如果不合法，则弹出对话框重新选择带教人员
    // 会修改memberList
    // 如果返回值为0，说明修改了单元格，不保存到文件中，再次点击确定键保存
    if(0 == teacherForRookie(memberList))   return;

    writeJsonData(Obj);

    QMessageBox::information(this, "保存", "人员信息保存成功！", QMessageBox::Yes);

    pStackWidget->setCurrentIndex(STACKWIDGET_MEMBERSCHEDULE_INDEX + 1);
    return;
}

void MemberSchedule::slot_btnCancel_clicked(void)
{
    // 返回到welcome界面
    pStackWidget->setCurrentIndex(STACKWIDGET_WELCOME_INDEX);

    return;
}

void MemberSchedule::slot_tableWidget_cellChanged(int row, int column)
{
    // 首先断开 cellChanged 信号的监听
    disconnect(pTable, &MyMemberTable::cellChanged, this, &MemberSchedule::slot_tableWidget_cellChanged);

    // 设置QTableWidgetItem样式
    pTable->setMemberItemStyle(QBrush(Qt::black), QFont("Microsoft YaHei", 11), row, column);

    // 再次连接 cellChanged 信号
    connect(pTable, &MyMemberTable::cellChanged, this, &MemberSchedule::slot_tableWidget_cellChanged);

    return;
}

void MemberSchedule::slot_pushButtonDelete_clicked(void)
{
    // 首先断开 cellChanged 信号的监听
    disconnect(pTable, &MyMemberTable::cellChanged, this, &MemberSchedule::slot_tableWidget_cellChanged);

    int row = 0;
    int answer = 0;
    QModelIndex idx;
    QTableWidgetItem *pItemName = NULL;

    QPushButton *senderObj=(QPushButton *)QObject::sender();
    if(NULL == senderObj){
        QLOG_DEBUG() << "NULL == senderObj";
        goto FUNC_OUT;
    }

    // 获取行号
    idx = pTable->indexAt(QPoint(senderObj->frameGeometry().x(), senderObj->frameGeometry().y()));
    row = idx.row();

    // 高亮当前行
    pTable->highLighterRow(SELETE_ROW_HIGHLIGHT_BACKGROUND_STYLE, row);

    // 如果删除的行没有数据，那么直接删除，不再询问
    pItemName = pTable->item(row, COLUMN_NAME);
    if(NULL == pItemName || "" == pItemName->text()){
        if(NULL != pItemName)   delete pItemName;
        pTable->CancelHighLighterRow(SELETE_ROW_DEFAULT_BACKGROUND_STYLE);
        pTable->removeMemberSpecificRow(row);
        goto FUNC_OUT;
    }

    // 弹出询问对话框
    answer = QMessageBox::question(this, "删除人员数据", "确定删除该行人员数据？", QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
    pTable->CancelHighLighterRow(SELETE_ROW_DEFAULT_BACKGROUND_STYLE);
    if (QMessageBox::Yes != answer)
        goto FUNC_OUT;

    pTable->removeMemberSpecificRow(row);

FUNC_OUT:
    // 再次连接 cellChanged 信号
    connect(pTable, &MyMemberTable::cellChanged, this, &MemberSchedule::slot_tableWidget_cellChanged);
    return;
}

void MemberSchedule::slot_pushButtonTeacherDelete_clicked()
{
    // 首先断开 cellChanged 信号的监听
    disconnect(pTable, &MyMemberTable::cellChanged, this, &MemberSchedule::slot_tableWidget_cellChanged);

    int row = 0;
    QModelIndex idx;
    MemberClass* pTmp = NULL;
    QTableWidgetItem *pItemName   = NULL;
    QTableWidgetItem *pItemTeacher   = NULL;

    QPushButton *senderObj=(QPushButton *)QObject::sender();
    if(NULL == senderObj){
        QLOG_DEBUG() << "NULL == senderObj";
        goto FUNC_OUT;
    }

    // 获取行号
    idx = pTable->indexAt(QPoint(senderObj->frameGeometry().x(), senderObj->frameGeometry().y()));
    row = idx.row();

    pItemName = pTable->item(row, COLUMN_NAME);
    pItemTeacher = pTable->item(row, COLUMN_TEACHER);
    if(NULL == pItemName || "" == pItemName->text() || NULL == pItemTeacher || "" == pItemTeacher->text()){
        QLOG_DEBUG() << "NULL == pItemName || "" == pItemName->text() || NULL == pItemTeacher || "" == pItemTeacher->text()";
        goto FUNC_OUT;
    }

    // 删除该成员带教人员
     pTmp = findMemberClassFromName(MEMBERLIST, pItemName->text());
    if(NULL == pTmp){
        QLOG_DEBUG() << "NULL == pTmp";
        goto FUNC_OUT;
    }
    pTmp->setTeacherName("");
    pItemTeacher->setText("");

FUNC_OUT:
    // 再次连接 cellChanged 信号
    connect(pTable, &MyMemberTable::cellChanged, this, &MemberSchedule::slot_tableWidget_cellChanged);
    return;
}

void MemberSchedule::slot_LevelComboBox_currentIndexChanged(int index)
{
    MemberClass* pTmp = NULL;
    QTableWidgetItem * pItemName = NULL;
    QTableWidgetItem * pItemTeacher = NULL;
    // 获取信号发送者的行号
    MyCombobox *senderObj=(MyCombobox *)QObject::sender();
    if(NULL == senderObj){
        QLOG_WARN() << "NULL == senderObj";
        return;
    }

    // 获取行号
    QModelIndex idx = pTable->indexAt(QPoint(senderObj->frameGeometry().x(), senderObj->frameGeometry().y()));

    // 设置Level tooltip
    setLevelToolTip(senderObj, senderObj->currentIndex());

    // 能力等级 列改变，对应能力值 列也改变
    int row = idx.row();

    // 能力等级 不为MEMBER_ABILITY_LEVEL_1时，删除带教人员
    pItemName = pTable->item(row, COLUMN_NAME);
    pItemTeacher = pTable->item(row, COLUMN_TEACHER);
    if(index != MEMBER_ABILITY_LEVEL_1 && NULL != pItemTeacher && "" != pItemTeacher->text()){
        // 删除该成员带教人员
         pTmp = findMemberClassFromName(MEMBERLIST, pItemName->text());
        if(NULL == pTmp){
            QLOG_WARN() << "NULL == pTmp";
            return;
        }
        pTmp->setTeacherName("");
        pItemTeacher->setText("");
    }

    return;
}

void MemberSchedule::slot_teacherDialogBtn_clicked()
{
    if(NULL == pSelectTeacherComBox || NULL == pSelectTeacherLabel){
        QLOG_WARN() << "NULL == pSelectTeacherComBox || NULL == pSelectTeacherLabel";
        return ;
    }

    // 请为<b>XXX</b>指定人员:
    QString stuName = pSelectTeacherLabel->text();
    // 14 是指除去姓名以外的长度
    stuName = stuName.mid(5, stuName.count() - 14);

    // 修改MEMBERLIST中对应成员
    QList<MemberClass*> memberList = MEMBERLIST;
    MemberClass* pTmp = findMemberClassFromName(memberList, stuName);
    if(NULL == pTmp){
        QLOG_WARN() << "NULL == pTmp";
        return ;
    }
     pTmp->setTeacherName(pSelectTeacherComBox->currentText());

    pSelectTeacherDialog->close();
    return;
}
